package com.mtconnect.service;

import com.mtconnect.common.Constant;
import com.mtconnect.model.CurrentDTO;
import com.mtconnect.model.SampleDTO;
import com.mtconnect.util.*;
import org.dom4j.*;
import org.dom4j.tree.DefaultText;
import org.jboss.resteasy.annotations.Form;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by Administrator on 2017/7/19.
 */
@Path("/")
public class MTConnect {

    private static final Logger LOGGER = LoggerFactory.getLogger(MTConnect.class);

    @GET
    @Path("{deviceName:.*}/probe")
    @Produces(MediaType.APPLICATION_XML)
    public String probe2Device(@PathParam("deviceName") String deviceName) {
        LOGGER.debug("param is {}", deviceName);
        boolean flag = false;
        // Header param set up
        Map<String, String> param = getHeader();
        //load xml file
        Document document = ResourceLoad.getDeviceRoot();
        Element header = document.getRootElement().addElement("Header");
        XMLUtil.additionalAttributes(header, param);

        XPath xPath = DocumentHelper.createXPath("//d:Device[@name='" + deviceName + "']");
        xPath.setNamespaceURIs(Constant.DEVICE_XMLNS);

        for (Document device : ResourceLoad.DEVICES) {
            Node node = xPath.selectSingleNode(device);
            if (Objects.nonNull(node)) {
                document.getRootElement().add(((Element) node).createCopy());
                flag = true;
                break;
            }
        }
        if (flag) {
            return document.asXML();
        } else {
            Document error = ResourceLoad.getErrorRoot();
            Element errorHeader = error.getRootElement().addElement("Header");
            XMLUtil.additionalAttributes(errorHeader, param);
            Element errors = error.getRootElement().addElement("Errors");
            Element error1 = errors.addElement("Error");
            error1.addAttribute("errorCode", "NO_DEVICE");
            error1.add(new DefaultText("Could not find the device '" + deviceName + "'"));
            return error.asXML();
        }
    }

    @GET
    @Path("/probe")
    @Produces(MediaType.APPLICATION_XML)
    public String probe() {
        // Header param set up
        Map<String, String> param = getHeader();
        //load xml file
        Document document = ResourceLoad.getDeviceRoot();
        Element header = document.getRootElement().addElement("Header");
        XMLUtil.additionalAttributes(header, param);
        Element devices = document.getRootElement().addElement("Devices");

        XPath xPath = DocumentHelper.createXPath("//d:Device");
        xPath.setNamespaceURIs(Constant.DEVICE_XMLNS);
        for (Document device : ResourceLoad.DEVICES) {
            List<Node> list = xPath.selectNodes(device);
            for (Node node : list) {
                devices.add(((Element) node).createCopy());
            }
        }
        return document.asXML();
    }

    @GET
    @Path("/current")
    @Produces(MediaType.APPLICATION_XML)
    public String current(@Form CurrentDTO currentDTO, @Context HttpServletResponse response) {
        LOGGER.debug("param is {}", currentDTO);
        // Header param setup
        Map<String, String> header = getHeader();
        String s = validateCurrent(currentDTO, header);
        if (!Objects.isNull(s)) {
            return s;
        }
        if (Objects.nonNull(currentDTO.getInterval())) {
            try {
                stream(currentDTO, response, header);
            } catch (IOException e) {
                LOGGER.warn("client closed ", e);
            } catch (InterruptedException e) {
                LOGGER.error("server error ,because thread interrupted", e);
                return "server error";
            }
            return null;
        } else {
            return fetchContent(currentDTO, header);
        }
    }

    @GET
    @Path("/{deviceName}/current")
    @Produces(MediaType.APPLICATION_XML)
    public String getOneCurrent(@Form CurrentDTO currentDTO, @PathParam("deviceName") String name, @Context HttpServletResponse response) {
        currentDTO.setDeviceName(name);
        LOGGER.debug("param is {}", currentDTO);
        // Header param setup
        Map<String, String> header = getHeader();
        String s = validateCurrent(currentDTO, header);
        if (!Objects.isNull(s)) {
            return s;
        }
        if (Objects.nonNull(currentDTO.getInterval())) {
            try {
                stream(currentDTO, response, header);
            } catch (IOException e) {
                LOGGER.warn("client closed ", e);
            } catch (InterruptedException e) {
                LOGGER.error("server error ,because thread interrupted", e);
                return "server error";
            }
            return null;
        } else {
            return fetchContent(currentDTO, header);
        }
    }

    @GET
    @Path("/sample")
    @Produces(MediaType.APPLICATION_XML)
    public String sample(@Form SampleDTO sampleDTO, @Context HttpServletResponse response) {
        LOGGER.debug("param is {}", sampleDTO);
        Map<String, String> header = getHeader();
        //参数做验证，并初始化对象中的null值
        String errorXML = validateSample(sampleDTO, header);
        if (errorXML != null) {
            return errorXML;
        }

        if (Objects.nonNull(sampleDTO.getInterval())) {
            try {
                stream(sampleDTO, response, header);
            } catch (IOException e) {
                LOGGER.warn("client closed ", e);
            } catch (InterruptedException e) {
                LOGGER.error("server error ,because thread interrupted", e);
                return "server error";
            }
            return null;
        } else {
            return fetchContent(sampleDTO, header);
        }
    }

    @GET
    @Path("/{deviceName}/sample")
    @Produces(MediaType.APPLICATION_XML)
    public String getOneSample(@Form SampleDTO sampleDTO, @PathParam("deviceName") String name, @Context HttpServletResponse response) {
        sampleDTO.setDeviceName(name);
        LOGGER.debug("param is {}", sampleDTO);
        Map<String, String> header = getHeader();
        //参数做验证，并初始化对象中的null值
        String errorXML = validateSample(sampleDTO, header);
        if (errorXML != null) {
            return errorXML;
        }
        if (Objects.nonNull(sampleDTO.getInterval())) {
            try {
                stream(sampleDTO, response, header);
            } catch (IOException e) {
                LOGGER.warn("client closed ", e);
            } catch (InterruptedException e) {
                LOGGER.error("server error ,because thread interrupted", e);
                return "server error";
            }
            return null;
        } else {
            return fetchContent(sampleDTO, header);
        }
    }

    @GET
    @Path("/assets")
    @Produces(MediaType.APPLICATION_XML)
    public String assets(@QueryParam("type") String type, @QueryParam("count") String count) {
        LOGGER.debug("param type is {} param count is {}", type, count);
        /*
            1.type以及count都是空的，那么将所有的Assets中的child Tag返回
            2.如果type非空，那么找到所有Assets中Child Tag的name是type
            3.如果type以及count都是非空的。那么先执行步骤2，在步骤2中所找到的child Tag数量大于count，那么就返回最新的结果，否则就返回child Tag
            4.如果type是空，count非空，那么找到所有的返回count数，所找到的元素大于count那么按照元素的timestamp属性排序，取最新的count个元素返回
         */
        Document assetsRoot = ResourceLoad.getAssetsRoot();
        // Header param set up
        Map<String, String> header = getHeader();
        Element element = assetsRoot.getRootElement().addElement("Header");
        XMLUtil.additionalAttributes(element, header);
        Element assets = assetsRoot.getRootElement().addElement("Assets");
        Document allAssets = ResourceLoad.ALL_ASSETS;
        List<Element> elements = allAssets.getRootElement().elements();

        //第一种情况
        if ((Objects.isNull(type) || "".equals(type))
                && (Objects.isNull(count) || "".equals(count))) {
            for (Element element1 : elements) {
                assets.add(element1.createCopy());
            }
            return assetsRoot.asXML();
            //第三种情况
        } else if (Objects.nonNull(type) && !type.equals("") && Objects.nonNull(count) && !count.equals("")) {
            List<Element> childes = new ArrayList<>();
            for (Element element1 : elements) {
                if (element1.getName().equals(type)) {
                    childes.add(element1);
                }
            }
            if (childes.size() > Integer.valueOf(count)) {
                Collections.sort(childes, (o1, o2) -> {
                    LocalDateTime o1Time = LocalDateTime.parse(o1.attributeValue("timestamp"));
                    LocalDateTime o2Time = LocalDateTime.parse(o2.attributeValue("timestamp"));
                    int i = o1Time.compareTo(o2Time);
                    if (i > 0) {
                        return -1;
                    } else if (i < 0) {
                        return 1;
                    }
                    return 0;
                });
                childes = childes.subList(0, Integer.valueOf(count));
            }
            for (Element element1 : childes) {
                assets.add(element1.createCopy());
            }
            return assetsRoot.asXML();
        } else {
            //第二种情况
            if (Objects.nonNull(type) && !type.equals("")) {
                for (Element element1 : elements) {
                    if (element1.getName().equals(type)) {
                        assets.add(element1.createCopy());
                    }
                }
                return assetsRoot.asXML();
            }
            //第四种情况
            if (Objects.nonNull(count) && !count.equals("")) {
                if (elements.size() > Integer.valueOf(count)) {
                    Collections.sort(elements, (o1, o2) -> {
                        LocalDateTime o1Time = LocalDateTime.parse(o1.attributeValue("timestamp"));
                        LocalDateTime o2Time = LocalDateTime.parse(o2.attributeValue("timestamp"));
                        int i = o1Time.compareTo(o2Time);
                        if (i > 0) {
                            return -1;
                        } else if (i < 0) {
                            return 1;
                        }
                        return 0;
                    });
                    elements = elements.subList(0, Integer.valueOf(count));
                }
                for (Element element1 : elements) {
                    assets.add(element1.createCopy());
                }
                return assetsRoot.asXML();
            }
        }
        return null;
    }

    @GET
    @Path("/assets/{assetsName}")
    @Produces(MediaType.APPLICATION_XML)
    public String getOnesAssets(@PathParam("assetsName") String assetsName, @Context HttpServletRequest request) {
        /*
            拿到所有的assetId，其中assetId可以使用;进行分隔
            /assets/a;bd;c
         */
        String requestURI = request.getRequestURI();
        String[] assetID = requestURI.split("/");
        assetsName = assetID[2];
        LOGGER.debug("param is {}", assetsName);

        Map<String, String> header = getHeader();
        List<Element> elements = ResourceLoad.ALL_ASSETS.getRootElement().elements();
        List<Element> child = new ArrayList<>();
        //如果有多个assetId
        if (assetsName.contains(";")) {
            String[] split = assetsName.split(";");
            Map<String, Object> map = new HashMap<>();
            for (String s : split) {
                for (Element element : elements) {
                    if (element.attributeValue("assetId").equals(s)) {
                        map.put(s, element);
                        child.add(element);
                    }
                }
            }
            if (child.size() == split.length) {//如果数量正好匹配则返回找到的元素
                Element rootElement = ResourceLoad.getAssetsRoot().getRootElement();
                Element element = rootElement.addElement("Header");
                XMLUtil.additionalAttributes(element, header);
                Element element1 = rootElement.addElement("Assets");
                for (Element element2 : child) {
                    element1.add(element2.createCopy());
                }
                return rootElement.asXML();
            }
            //元素数量不匹配
            String assetIds = "";
            for (String s : split) {
                if (!map.containsKey(s)) {
                    assetIds = s + ";";
                }
            }
            //找到正确的assetId返回错误信息
            return createAssetsErrorXML(header, assetIds).asXML();
        }
        //只有一个assetId
        for (Element element : elements) {
            if (element.attributeValue("assetId").equals(assetsName)) {
                child.add(element);
            }
        }
        if (child.isEmpty() || child.size() > 1) {//如果没找到，或者数量大于一个，返回错误XML
            return createAssetsErrorXML(header, assetsName).asXML();
        }
        Element rootElement = ResourceLoad.getAssetsRoot().getRootElement();
        Element element = rootElement.addElement("Header");
        XMLUtil.additionalAttributes(element, header);
        Element element1 = rootElement.addElement("Assets");
        element1.add(child.get(0).createCopy());
        return rootElement.asXML();
    }

    /**
     * 创建Assets错误XML文件
     *
     * @param header     Header元素中的attribute信息
     * @param assetsName 错误的assets元素id
     * @return 完整的错误文档
     */
    private Document createAssetsErrorXML(Map<String, String> header, String assetsName) {
        Document errorRoot = ResourceLoad.getErrorRoot();
        Element rootElement = errorRoot.getRootElement();
        Element element = rootElement.addElement("Header");
        XMLUtil.additionalAttributes(element, header);
        Element error = rootElement.addElement("Errors").addElement("Error");
        error.addAttribute("errorCode", "ASSET_NOT_FOUND");
        error.add(new DefaultText("Could not find the asset(s) '" + assetsName + "'"));
        return errorRoot;
    }

    /**
     * 生成错误的XML文档
     * <p>
     * 本方法只生成主体错误XML文档，详细的错误元素属性以及文本内容需要再次进行填充。
     *
     * @param param Header元素的属性键值对。
     * @return 创建完成的错误XML文档。
     */
    private Document createErrorXML(Map<String, String> param) {
        Document errorRoot = ResourceLoad.getErrorRoot();
        Element rootElement = errorRoot.getRootElement();
        Element header = rootElement.addElement("Header");
        XMLUtil.additionalAttributes(header, param);
        Element errors = rootElement.addElement("Errors");
        errors.addElement("Error");
        return errorRoot;
    }

    /**
     * 填充count参数错误的element元素
     *
     * @param element 需要填充的元素
     * @return 填充完整的element元素
     */
    private Element createCountError(Element element) {
        element.addAttribute("errorCode", "INVALID_REQUEST");
        element.add(new DefaultText("invalid count parameter"));
        return element;
    }

    /**
     * 生产设备不存在错误信息
     *
     * @param element    错误根文件
     * @param deviceName 无法找到的设备名称
     * @return 填充完整的xml错误文档
     */
    private Element createDeviceNameError(Element element, String deviceName) {
        Element errors = element.element("Errors");
        Element error = errors.element("Error");
        Element element1 = error.addAttribute("errorCode", "NO_DEVICE");
        element1.add(new DefaultText("'" + deviceName + "'" + " is not a valid Device"));
        return element;
    }

    /**
     * 填充from参数错误element参数
     *
     * @param element 需要填充的元素
     * @param flag    如果是true则表示from小于firstSequence值，如果是false则表示from大于lastSequence值
     * @return 填充完成的元素
     */
    private Element createFromError(Element element, boolean flag) {
        element.add(new DefaultText("invalid from parameter"));
        if (flag) {
            element.addAttribute("errorCode", "INVALID_REQUEST");
        } else {
            element.addAttribute("errorCode", "OUT_OF_RANGE");
        }
        return element;
    }

    /**
     * 生成xPath无效或错误响应element
     *
     * @param element 需要填充的元素
     * @param xPath   xPath表达式文本
     * @return 填充完成的元素
     */
    private Element createXPathError(Element element, String xPath) {
        element.addAttribute("errorCode", "INVALID_XPATH");
        element.add(new DefaultText("'" + xPath + "' is not a valid XPATH"));
        return element;
    }

    /**
     * 创建probe、sample、current方法所需的头部信息
     *
     * @return 返回填充完成的头部信息。
     */
    private static Map<String, String> getHeader() {
        Map<String, String> param = new HashMap<>();
        param.put(Constant.CREATION_TIME, DateUtil.getUTCTime());
        param.put(Constant.INSTANCE_ID, "0");
        param.put(Constant.SENDER, "http://127.0.0.1/");
        param.put(Constant.BUFFER_SIZE, "4294967295");
        param.put(Constant.ASSET_BUFF_SIZE, "4294967295");
        long currSeqVal = Sequence.getCurrSeqVal();
        param.put(Constant.LAST_SEQ, String.valueOf(currSeqVal));//当前数据库中sequence的最大值，即当前值。
        param.put(Constant.NEXT_SEQ, String.valueOf((currSeqVal + 1)));//当前值+1
        long result = currSeqVal - Constant.MAX_SEQUENCE;
        if (result > 0) {
            param.put(Constant.FIRST_SEQ, String.valueOf(result));
        } else {
            param.put(Constant.FIRST_SEQ, "0");
        }
        param.put(Constant.VERSION, "1.3");
        param.put(Constant.ASSET_COUNT, ResourceLoad.ALL_ASSETS.getRootElement().elements().size() + "");
        return param;
    }

    /**
     * 对SampleDTO对象中的属性做验证，并对一些没有赋值的属性做初始化
     *
     * @param sampleDTO 客户端传递的参数实体类
     * @param header    XML头元素中的attribute
     * @return 如果是null则没有错误，否则返回完整的错误XML文件，可用于直接反馈client。
     */
    private String validateSample(@Form SampleDTO sampleDTO, Map<String, String> header) {
        //------------------------------对参数做验证，如果错误则返回错误信息------------------------------------------------------------------
        if (Objects.nonNull(sampleDTO.getxPath())) {
            try {
                DocumentHelper.createXPath(sampleDTO.getxPath());
            } catch (InvalidXPathException e) {
                LOGGER.warn("XPath is invalid {}", sampleDTO.getxPath());
                Document errorXML = createErrorXML(header);
                createXPathError(errorXML.getRootElement().element("Errors").element("Error"), sampleDTO.getxPath());
                return errorXML.asXML();
            }
        }
        if (Objects.nonNull(sampleDTO.getFrom())) {
            if (sampleDTO.getFrom() < Long.valueOf(header.get(Constant.FIRST_SEQ))) {
                LOGGER.debug("from < first sequence({} < {})", sampleDTO.getFrom(), header.get(Constant.FIRST_SEQ));
                Document errorXML = createErrorXML(header);
                createFromError(errorXML.getRootElement().element("Errors").element("Error"), true);
                return errorXML.asXML();
            } else if (sampleDTO.getFrom() > Long.valueOf(header.get(Constant.LAST_SEQ)) + 1) {
                LOGGER.debug("from > last sequence({} > {})", sampleDTO.getFrom(), header.get(Constant.LAST_SEQ) + 1);
                Document errorXML = createErrorXML(header);
                createFromError(errorXML.getRootElement().element("Errors").element("Error"), false);
                return errorXML.asXML();
            }
        }
        if (Objects.nonNull(sampleDTO.getCount()) && sampleDTO.getCount() < 1) {
            LOGGER.debug("count parameter < 1 (count is {})", sampleDTO.getCount());
            Document errorXML = createErrorXML(header);
            createCountError(errorXML.getRootElement().element("Errors").element("Error"));
            return errorXML.asXML();
        }
        if (Objects.nonNull(sampleDTO.getDeviceName())) {
            XPath xPath = DocumentHelper.createXPath("//d:Device[@name='" + sampleDTO.getDeviceName() + "']");
            xPath.setNamespaceURIs(Constant.DEVICE_XMLNS);
            Node node = xPath.selectSingleNode(ResourceLoad.ALL_DEVICE);
            if (Objects.isNull(node)) {
                Document errorXML = createErrorXML(header);
                createDeviceNameError(errorXML.getRootElement(), sampleDTO.getDeviceName());
                return errorXML.asXML();
            }
        }
        //---------------------------------------------------------参数效验结束----------------------------------------------------------------------

        //-------------------------------------------------对一些必须有值的空参进行赋值，以及参数更正工作----------------------------------------------------------
        if (Objects.nonNull(sampleDTO.getInterval())) {
            Integer interval = Integer.parseInt(sampleDTO.getInterval());
            if (Objects.nonNull(interval) && interval <= 0) {
                sampleDTO.setInterval("5000");
            }
        }
        if (Objects.isNull(sampleDTO.getFrom())) {
            sampleDTO.setFrom(header.get("firstSequence"));
        }
        if (Objects.isNull(sampleDTO.getCount())) {
            sampleDTO.setCount("100");
        }
        //------------------------------------------------赋值结束--------------------------------------------------------------
        return null;
    }

    /**
     * 对currentAPI中的参数进行验证，并对一些没有赋值的参数进行初始化
     *
     * @param currentDTO 参数实体类
     * @param header     header元素中的属性
     * @return null表示没有错误信息。否则返回完整的错误XML文件，可用于直接反馈client。
     */
    private String validateCurrent(CurrentDTO currentDTO, Map<String, String> header) {
        Element rootElement = ResourceLoad.getErrorRoot().getRootElement();
        if (Objects.nonNull(currentDTO.getAt())) {
            long at = Long.parseLong(currentDTO.getAt());
            long first = Long.parseLong(header.get(Constant.FIRST_SEQ));
            long last = Long.parseLong(header.get(Constant.LAST_SEQ));

            if (at < first) {
                Element header1 = rootElement.addElement(Constant.HEADER);
                XMLUtil.additionalAttributes(header1, header);
                Element element = rootElement.addElement(Constant.ERRORS);
                Element element1 = element.addElement(Constant.ERROR);
                element1.addAttribute(Constant.ERROR_CODE, "INVALID_REQUEST");
                element1.add(new DefaultText("invalid from parameter"));
                return rootElement.getDocument().asXML();
            } else if (at > (last + 1)) {
                Element header1 = rootElement.addElement(Constant.HEADER);
                XMLUtil.additionalAttributes(header1, header);
                Element element = rootElement.addElement(Constant.ERRORS);
                Element element1 = element.addElement(Constant.ERROR);
                element1.addAttribute(Constant.ERROR_CODE, "OUT_OF_RANG");
                element1.add(new DefaultText("invalid from parameter"));
                return rootElement.getDocument().asXML();
            }
        }
        if (Objects.nonNull(currentDTO.getAt()) && Objects.nonNull(currentDTO.getInterval())) {
            Element header1 = rootElement.addElement(Constant.HEADER);
            XMLUtil.additionalAttributes(header1, header);
            Element element = rootElement.addElement(Constant.ERRORS);
            Element element1 = element.addElement(Constant.ERROR);
            element1.addAttribute(Constant.ERROR_CODE, "INVALID_REQUEST");
            element1.add(new DefaultText("You cannot specify both the at and frequency arguments to a current request"));
            return rootElement.getDocument().asXML();
        }

        if (Objects.isNull(currentDTO.getAt()) || currentDTO.getAt().isEmpty()) {
            currentDTO.setAt(header.get(Constant.LAST_SEQ));
        }
        return validateSample(currentDTO, header);
    }

    /**
     * 获得完整的设备信息，返回客户端
     *
     * @param sampleDTO 客户端传递过来的参数
     * @param header    组装好的头文件信息
     * @return 完整的响应XML文档
     */
    private String fetchContent(@Form SampleDTO sampleDTO, Map<String, String> header) {
        //-----------------------------------获取完整DeviceStream元素---------------------------------
        try (JDBCTemplete jdbcTemplete = new JDBCTemplete()) {
            SampleService sampleService = new SampleService(jdbcTemplete);
            List<Element> elements;
            if (Objects.isNull(sampleDTO.getxPath())) {
                elements = sampleService.nonePath(sampleDTO);
            } else {
                elements = sampleService.selectByXPath(sampleDTO);
            }
            //--------------------------------------end--------------------------------------------------

            //--------------------------------------load xml content-----------------------------------------

            if (Objects.isNull(elements)) {
                if (Objects.nonNull(sampleDTO.getxPath())) {
                    Document errorXML = createErrorXML(header);
                    createXPathError(errorXML.getRootElement().element("Errors").element("Error"), sampleDTO.getxPath());
                    return errorXML.asXML();
                } else {
                    return "SERVICE INTERNAL ERROR";
                }
            } else {
                Document streamsRoot = ResourceLoad.getStreamsRoot();
                Element rootElement = streamsRoot.getRootElement();
                Element headerElement = rootElement.addElement("Header");
                //如果stream中有值，则header中的nextSequence要设置为stream中最大sequence+1，否则不用动
                if (!elements.isEmpty()) {
                    Long sequence = 0L;
                    for (Element element : elements) {
                        List<Node> list = element.selectNodes("//*[@sequence]");
                        for (Node node : list) {
                            Element e = (Element) node;
                            String value = e.attributeValue("sequence");
                            long var = Long.parseLong(value);
                            if (sequence.compareTo(var) < 0) {
                                sequence = var;
                            }
                        }
                    }
                    header.replace(Constant.NEXT_SEQ, sequence.toString());
                }
                XMLUtil.additionalAttributes(headerElement, header);
                Element stream = rootElement.addElement("Streams");
                for (Element element : elements) {
                    stream.add(element.createCopy());
                }
                return streamsRoot.asXML().replace("xmlns=\"\"", "");
            }
        }
    }

    /**
     * sample 下流式返回
     *
     * @param sampleDTO
     * @param response
     * @param header
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    private void stream(@Form SampleDTO sampleDTO, @Context HttpServletResponse response, Map<String, String> header) throws IOException, InterruptedException {
        response.setStatus(HttpServletResponse.SC_OK);
        String boundary = UUID.randomUUID().toString();
        response.setContentType("multipart/x-mixed-replace;boundary=" + boundary);
        ServletOutputStream outputStream = response.getOutputStream();
        long sleepTime = Long.parseLong(sampleDTO.getInterval());
        BigDecimal a = new BigDecimal(sleepTime);
        BigDecimal b = new BigDecimal(10000L);
        BigDecimal tempTime = a.divideToIntegralValue(b);
        BigDecimal remainTime = a.subtract(b.multiply(tempTime));

        do {
            byte[] bytes = fetchContent(sampleDTO, header).getBytes();
            outputStream.println("--" + boundary);
            outputStream.println("Content-Type: application/xml");
            outputStream.println("Content-length:" + bytes.length);
            outputStream.write(bytes);
            outputStream.println();
            if (tempTime.intValue() > 0) {
                for (int i = 0, count = tempTime.intValue(); i < count; i++) {
                    TimeUnit.MILLISECONDS.sleep(10000);
                    Document streamsRoot = ResourceLoad.getStreamsRoot();
                    streamsRoot.clearContent();
                    Element element = streamsRoot.addElement("Header");
                    //sample需要将nextSequence设置为header参数中的nextSequence
                    if (sampleDTO instanceof SampleDTO) {
                        Map<String, String> map = getHeader();
                        map.replace(Constant.NEXT_SEQ, header.get(Constant.NEXT_SEQ));
                        XMLUtil.additionalAttributes(element, map);
                    } else {
                        XMLUtil.additionalAttributes(element, header);
                    }
                    streamsRoot.addElement("Stream");
                    outputStream.println("--" + boundary);
                    outputStream.println("Content-Type: application/xml");
                    outputStream.println("Content-length:" + bytes.length);
                    outputStream.write(bytes);
                    outputStream.println();
                }
            }
            TimeUnit.MILLISECONDS.sleep(remainTime.longValue());
            //只有sampleDTO需要做这步,将from设置为from+count,若无count,则count=100
            if (sampleDTO instanceof SampleDTO) {
                if (Objects.isNull(sampleDTO.getCount())) {
                    sampleDTO.setFrom(String.valueOf(sampleDTO.getFrom() + 100));
                } else {
                    sampleDTO.setFrom(String.valueOf(sampleDTO.getFrom() + sampleDTO.getCount()));
                }
            }
            header = getHeader();
        } while (true);
    }

    public static void main(String[] args) {

        LocalDateTime now = LocalDateTime.now();

        LocalDateTime parse = LocalDateTime.parse("2017-09-26T13:55:22");

        LOGGER.info("现在时间是：{},解析时间是：{}", now, parse);

        int i = now.compareTo(parse);

        LOGGER.info("比较结果是：{}", i);
    }
}
